﻿using MathNet.Numerics;
using SeeSharpTools.JY.ArrayUtility;
using SeeSharpTools.JY.DSP.Fundamental;
using Sunny.UI;
using System;
using System.Data;
using System.Linq;

namespace SeeSharpTools.Demo
{
    public partial class FormPeriodgram : UIPage
    {
        private bool isRunning = false;

        public FormPeriodgram()
        {
            InitializeComponent();

            uiComboBox_ChannelType.SelectedIndex = 0;
            uiComboBox_WindowType.Items.AddRange(Enum.GetNames(typeof(WindowType)));
            uiComboBox_SpectrumUnit.Items.AddRange(Enum.GetNames(typeof(SpectrumUnits)));
            uiComboBox_WindowType.SelectedIndex = 2;
            uiComboBox_SpectrumType.SelectedIndex = 1;
            uiComboBox_SpectrumUnit.SelectedIndex = 5;

            slide_FirstFreq.Max = 500;
            slide_FirstFreq.Min = 0;
            slide_FirstFreq.Value = 50;
            slide_SecondFreq.Max = 500;
            slide_SecondFreq.Min = 0;
            slide_SecondFreq.Value = 140;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            double sampleRate = 1000;
            double[] t = Generate.LinearRange(0, 1 / sampleRate, 1 - 1 / sampleRate);
            double[] x1 = t.Select(num => Math.Sin(2 * Math.PI * slide_FirstFreq.Value * num)).ToArray();
            double[] x2 = t.Select(num => Math.Sin(2 * Math.PI * slide_SecondFreq.Value * num)).ToArray();
            double[] noise = new double[t.Length];
            Generation.UniformWhiteNoise(ref noise, 0);

            double df;
            bool psd = uiComboBox_SpectrumType.SelectedIndex == 0;
            if (uiComboBox_ChannelType.SelectedIndex == 0)
            {
                double[] x = new double[t.Length];
                for (int i = 0; i < x.Length; i++)
                {
                    x[i] = x1[i] + 2 * x2[i] + 0.1 * noise[i];
                }

                double[] sp = new double[x.Length / 2];
                Spectrum.PowerSpectrum(x, sampleRate, ref sp, out df, (SpectrumUnits)Enum.Parse(typeof(SpectrumUnits), uiComboBox_SpectrumUnit.Text), (WindowType)Enum.Parse(typeof(WindowType), uiComboBox_WindowType.Text), double.NaN, psd);
                easyChartX1.Plot(t, x);
                easyChartX2.Plot(sp, 0, df);
            }
            else
            {
                x1 = x1.Zip(noise, (a, b) => a + 0.1 * b).ToArray();
                x2 = x2.Zip(noise, (a, b) => 2 * a + 0.1 * b).ToArray();
                double[,] combined = new double[2, x1.Length];
                ArrayManipulation.ReplaceArraySubset(x1, ref combined, 0, MajorOrder.Row);
                ArrayManipulation.ReplaceArraySubset(x2, ref combined, 1, MajorOrder.Row);

                double[,] sp = new double[2, x1.Length / 2];
                double[] sp1 = new double[x1.Length / 2];
                Spectrum.PowerSpectrum(x1, sampleRate, ref sp1, out df, (SpectrumUnits)Enum.Parse(typeof(SpectrumUnits), uiComboBox_SpectrumUnit.Text), (WindowType)Enum.Parse(typeof(WindowType), uiComboBox_WindowType.Text), double.NaN, psd);
                ArrayManipulation.ReplaceArraySubset(sp1, ref sp, 0, MajorOrder.Row);
                Spectrum.PowerSpectrum(x2, sampleRate, ref sp1, out df, (SpectrumUnits)Enum.Parse(typeof(SpectrumUnits), uiComboBox_SpectrumUnit.Text), (WindowType)Enum.Parse(typeof(WindowType), uiComboBox_WindowType.Text), double.NaN, psd);
                ArrayManipulation.ReplaceArraySubset(sp1, ref sp, 1, MajorOrder.Row);

                easyChartX1.Plot(t, combined);
                easyChartX2.Plot(sp, 0, df);
            }

            easyChartX1.AxisX.Title = "时间 (s)";
            easyChartX1.AxisY.Title = "幅度";
            if (uiComboBox_SpectrumType.SelectedIndex == 0)
            {
                easyChartX2.AxisY.Title = "功率谱密度 (dB/Hz)";
            }
            else
            {
                easyChartX2.AxisY.Title = "功率谱 (dB)";
            }
            easyChartX2.AxisX.Title = "频率 (Hz)";
        }

        private void uiSymbolButton_Click(object sender, EventArgs e)
        {
            if (isRunning)
            {
                timer1.Stop();
                uiSymbolButton.Symbol = 61515;
                isRunning = false;
            }
            else
            {
                timer1.Start();
                uiSymbolButton.Symbol = 61516;
                isRunning = true;
            }
        }
    }
}